package com.duoec.dw.lineage.service.impl;

import com.duoec.dw.lineage.dto.TableInfoDto;
import com.duoec.dw.lineage.exceptions.LineageAnalyseException;
import com.duoec.dw.lineage.exceptions.MySqlSchemaNotFoundException;
import com.duoec.dw.lineage.service.LineageTableService;
import com.duoec.dw.lineage.service.MySqlAnalyser;
import com.duoec.dw.lineage.service.MySqlSchemaService;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Objects;

/**
 * @author xuwenzhen
 */
@Service
public class MySqlSchemaServiceImpl implements MySqlSchemaService {
    private static final String API = "/get_info_schema/";
    public static final String STR_DB_NAME = "db_name";
    public static final String STR_TB_NAME = "tb_name";
    public static final String ERROR_MESSAGE = "'msg'";
    private static final String STR_DOT = ".";

    @Value("${sql-audit.url:https://sql-audit.duoec.com/}")
    private String sqlAuditUrl;

    @Autowired
    private MySqlAnalyser mySqlAnalyser;

    @Autowired
    private OkHttpClient okHttpClient;

    /**
     * 查询MySQL库中某个表的基本信息
     *
     * @param databaseName 库名
     * @param tableName    表名
     * @return 表的Schema信息
     */
    @Override
    public TableInfoDto getTableInfo(String databaseName, String tableName) {
        //尝试从运行时中加载
        TableInfoDto table = LineageTableService.getTable(databaseName + STR_DOT + tableName);
        if (table != null) {
            return table;
        }

        String schema = getTableSchema(databaseName, tableName);
        table = mySqlAnalyser.schemaAnalyse(schema);
        table.setDatabaseName(databaseName);
        return table;
    }

    private String getTableSchema(String databaseName, String tableName) {
        HttpUrl url = Objects.requireNonNull(HttpUrl.parse(sqlAuditUrl + API)).newBuilder()
                .addQueryParameter(STR_DB_NAME, databaseName)
                .addQueryParameter(STR_TB_NAME, tableName)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            String bodyStr = "";
            if (response.body() != null) {
                bodyStr = Objects.requireNonNull(response.body()).string();
            }
            if (!response.isSuccessful() || bodyStr.contains(ERROR_MESSAGE)) {
                throw new MySqlSchemaNotFoundException("获取表: " + databaseName + STR_DOT + tableName + " schema失败：status=" + response.code() + ", body=" + bodyStr);
            } else {
                return bodyStr;
            }
        } catch (IOException e) {
            throw new LineageAnalyseException("获取表: " + databaseName + STR_DOT + tableName + " schema失败", e);
        }
    }
}
